<template>
  <div>
    <SetAddress
      :deviceName="deviceName"
      :slaveId="props.slaveId"
      :registerType="currentRegisterType"
      :dialogVisible="addressDialogVisible"
      :setAddressDialogVisible="setAddressDialogVisible"
      @setSuccess="setSuccess"
    />
    <CoilRegister ref="coilRegisterRef" :deviceName="deviceName" slaveId="slaveId" />
    <HoldingRegister
      ref="holdingRegisterRef"
      :deviceName="deviceName"
      :slaveId="slaveId"
    />
  </div>
  <el-tabs
    v-model="currentRegisterType"
    type="card"
    class="tabs"
    @tab-click="handleClick"
  >
    <el-tab-pane
      v-for="registerType in registerTypeList"
      :key="registerType.index"
      :label="registerType.name"
      :name="registerType.index"
    >
      <div class="bar">
        <el-space>
          <el-button type="primary" @click="handleSetAddress()">
            <el-icon style="vertical-align: middle">
              <Setting />
            </el-icon>
            <span style="vertical-align: middle"> 设置地址范围 </span>
          </el-button>
          <el-button
            type="primary"
            class="write-btn"
            @click="writeRegister()"
            v-if="
              currentRegisterType == RegisterType.coil ||
              currentRegisterType == RegisterType.holding
            "
          >
            <el-icon style="vertical-align: middle">
              <Edit />
            </el-icon>
            <span style="vertical-align: middle"> {{ writeRegisterLabel }} </span>
          </el-button>
          <el-select v-if="isAutoRead" v-model="readInterval" style="width: 100px">
            <el-option
              v-for="item in readIntervalOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
          <el-switch
            v-model="isAutoRead"
            inline-prompt
            size="large"
            style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
            active-text="自动读取"
            inactive-text="手动读取"
            @change="autoRead"
          />
        </el-space>
      </div>
      <div>
        <Table
          :deviceName="deviceName"
          :slaveId="props.slaveId"
          :registerType="currentRegisterType"
          :tableHeader="tableDataMap[currentRegisterType]?.tableHeader || []"
          :tableData="tableDataMap[currentRegisterType]?.tableData || []"
        />
      </div>
    </el-tab-pane>
  </el-tabs>
</template>

<script lang="ts" setup name="Slave">
import {ref, onMounted, watch} from "vue";
import {ElMessage, type TabsPaneContext} from "element-plus";
import Table from "./Table.vue";
import {useRegisterStore} from "@/stores/register.ts";
import {useDeviceStore} from "@/stores/device.ts";
import {Edit, Setting} from "@element-plus/icons-vue";
import SetAddress from "./SetAddress.vue";
import {TableHeader} from "@/types/device.ts";
import {type RegisterAddress, RegisterType} from "@/types/register.ts";
import HoldingRegister from "@/components/write_register/HoldingRegister.vue";
import {writeRegister as writeRegisterApi} from "@/api/slaveApi.ts";
import CoilRegister from "@/components/write_register/CoilRegister.vue";

const registerStore = useRegisterStore();
const registerTypeList = registerStore.registerTypeList;
const deviceStore = useDeviceStore();
const currentRegisterType = ref(1);
const tableDataMap = ref<{
  [key: number]: {
    tableHeader: string[];
    tableData: any;
  };
}>({});
const addressDialogVisible = ref(false);
const registerAddress = ref<RegisterAddress>({
  registerType: 1,
  startAddress: 0,
  endAddress: 0
});
const isAutoRead = ref(false);
const readIntervalOptions = ref([
  {
    value: 50,
    label: '50ms',
  },
  {
    value: 100,
    label: '100ms',
  },
  {
    value: 200,
    label: '200ms',
  },
  {
    value: 500,
    label: '500ms',
  },
  {
    value: 1000,
    label: '1s',
  },
  {
    value: 2000,
    label: '2s',
  },
])
const readInterval = ref(1000);
const writeRegisterLabel = ref();
const holdingRegisterRef = ref();
const coilRegisterRef = ref();

let props = defineProps({
  simulationStatus: {
    type: Boolean,
  },
  deviceName: {
    type: String,
    required: true,
  },
  slaveId: {
    type: Number,
    required: true,
  },
});

function setAddressDialogVisible(value: boolean) {
  addressDialogVisible.value = value;
}

const setSuccess = async () => {
  setAddressDialogVisible(false);
  await fetchDeviceTable(props.deviceName, props.slaveId, currentRegisterType.value);
  ElMessage({
    type: "success",
    message: `设置寄存器地址成功!`,
    duration: 3000,
  });
};

// 封装数据获取逻辑
const fetchRegisterTypeList = async () => {
  currentRegisterType.value = 1; // 设置默认激活的 Tab
  await fetchDeviceTable(props.deviceName, props.slaveId, currentRegisterType.value);
};

const fetchDeviceTable = async (
  deviceName: string,
  slaveId: number,
  registerType: number
) => {
  const data = await deviceStore.getSlaveTable(deviceName, slaveId, registerType)?.catch(() => []);
  tableDataMap.value[registerType] = {
    tableHeader: Object.values(TableHeader),
    tableData: data,
  };
  if (data.length === 0) {
    registerAddress.value.startAddress = 0;
    registerAddress.value.endAddress = 0;
  } else {
    registerAddress.value.startAddress = data[0].address;
    registerAddress.value.endAddress = data[data.length - 1].address;
  }
};

const readAllRegisters = async (deviceName: string, slaveId: number, registerType: number) => {
  const data = await deviceStore.readRegister(deviceName, slaveId, registerType, registerAddress.value.startAddress,
    registerAddress.value.endAddress)?.catch(() => []);
  tableDataMap.value[registerType] = {
    tableHeader: Object.values(TableHeader),
    tableData: data,
  };
};

const writeRegister = () => {
  if (currentRegisterType.value === RegisterType.coil) {
    coilRegisterRef.value?.openDialog();
  } else {
    holdingRegisterRef.value?.openDialog();
  }
};

const handleClick = async (tab: TabsPaneContext, event: Event) => {
  if (tab.index !== undefined) {
    const index = parseInt(tab.index);
    currentRegisterType.value = index + 1;
    await fetchDeviceTable(props.deviceName, props.slaveId, currentRegisterType.value);
    updateWriteRegisterLabel();
  }
};

const handleSetAddress = () => {
  setAddressDialogVisible(true);
};

const autoRead = () => {
  let timeoutId: number | null = null;

  const fetchLoop = async () => {
    if (!isAutoRead.value) return; // 提前终止条件

    try {
      await readAllRegisters(props.deviceName, props.slaveId, currentRegisterType.value);
    } catch (error) {
      console.error('读取失败:', error);
    }
    // 正常轮询
    timeoutId = setTimeout(fetchLoop, readInterval.value);
  };

  if (isAutoRead.value) {
    fetchLoop(); // 立即启动首次请求
  } else {
    if (timeoutId !== null) {
      clearTimeout(timeoutId);
      timeoutId = null;
    }
  }
};

const updateWriteRegisterLabel = () => {
  if (currentRegisterType.value == RegisterType.coil) {
    writeRegisterLabel.value = "(05/15)写入线圈寄存器"
  } else if (currentRegisterType.value == RegisterType.holding) {
    writeRegisterLabel.value = "(06/16)写入保持寄存器"
  }
}

watch(
  () => props.deviceName,
  async (newValue) => {
    await fetchRegisterTypeList();
  }
);

// // 在组件挂载时首次获取数据
onMounted(() => {
  fetchRegisterTypeList();
  updateWriteRegisterLabel();
})
;
</script>

<style scoped>
.tabs {
  margin-top: 0 !important;
  margin-left: 0 !important;
  margin-bottom: 0 !important;
}

.bar {
  margin-top: 0;
  margin-bottom: 10px;
  height: 35px;
  display: flex;
  gap: 10px;
  align-items: center;
}

/* 使用深度选择器穿透scoped限制 */
:deep(.write-btn) {
  background-color: #ff6d33 !important;
  border-color: #ff6d33 !important;
  color: white !important;
}

/* 处理悬停状态 */
:deep(.write-btn:hover) {
  background-color: #ff8d66 !important;
  border-color: #ff8d66 !important;
}

/* 处理点击状态 */
:deep(.write-btn:active) {
  background-color: #e65c2b !important;
  border-color: #e65c2b !important;
}
</style>
